import Editor from "@monaco-editor/react";
import { useEffect, useRef, useState } from "react";

// 1. 定义你的专属字段列表
const myKeywords = [
  "单号",
  "产品编码",
  "产品名称",
  "计划量",
  "生产日期",
];

// 1. 定义我们的自定义函数“字典”
// 我们使用对象数组，这样可以存储更多信息，如文档和代码片段
const CUSTOM_FUNCTIONS = [
  {
    label: 'SUM',
    // 允许多个值，用 ... 表示
    insertText: 'SUM(${1:value1}, ${2:value2}, ...)',
    documentation: '计算一组值的总和。',
    detail: '聚合函数 SUM(value1, value2, ...)',
  },
  {
    label: 'AVG',
    insertText: 'AVG(${1:value}, ${2:value2}, ...)',
    documentation: '计算一组值的平均值。',
    detail: '聚合函数 AVG(value1, value2, ...)',
  },
  {
    label: 'COUNT',
    insertText: 'COUNT(${1:value}, ${2:value2}, ...)',
    documentation: '计算行数或非NULL值的数量。',
    detail: '聚合函数 COUNT(value1, value2, ...)',
  },
];


function CustomFormulaEditor() {
  const languageId = "myFormulaLanguage"; // 给你的自定义语言起个名字

  const completionProviderRef = useRef(null);

  useEffect(() => {
    const provider = completionProviderRef.current;
    return () => {
      provider?.dispose();
    };
  }, []);

  /**
   * 编辑器挂载完毕后执行此函数
   * @param {object} editor - 编辑器实例
   * @param {object} monaco - Monaco Editor 的核心 API
   */
  function handleEditorDidMount(editor, monaco) {
    if (completionProviderRef.current) {
      completionProviderRef.current.dispose();
    }

    // --- 2. 注册自定义语言和语法规则 ---

    // a. 注册语言 ID
    monaco.languages.register({ id: languageId });

    // b. 定义语法规则 (使用 Monarch tokenizer)
    // 我们用正则表达式来匹配 [关键字] 格式
    const keywordsRegex = `(${myKeywords.join("|")})`;
    const validFieldRegex = new RegExp(`\\[${keywordsRegex}\\]`);

    monaco.languages.setMonarchTokensProvider(languageId, {

      brackets: [
        ['(', ')', 'delimiter.parenthesis'],
        ['[', ']', 'delimiter.square'],
      ],

      // 将函数名也加入词法规则
      custom_functions: CUSTOM_FUNCTIONS.map(f => f.label),

      tokenizer: {
        root: [
          // 规则一：匹配我们定义的有效字段，并标记为 "custom-keyword"
          [validFieldRegex, "custom-keyword"],

          // 规则二：匹配其他被中括号包围的文本，标记为 "invalid-keyword" (可选)
          [/\[.*?\]/, "invalid-keyword"],
          // 规则三：匹配自定义函数，并标记为 "custom-function"
          [/[a-zA-Z_]\w*/, {
            cases: {
              '@custom_functions': 'custom-function',
              '@default': 'identifier'
            }
          }],
          // 规则四：匹配括号 () 和 []
          [/[()\[\]]/, '@brackets'],
        ],
      },
    });

    // --- 3. 创建并应用自定义主题 ---
    monaco.editor.defineTheme("myCoolTheme", {
      base: "vs", // 基于暗色主题
      inherit: true, // 继承基础主题的设置
      rules: [
        // 定义我们上面标记的 token 的颜色
        { token: "custom-keyword", foreground: "00b375" }, // 绿色
        { token: "invalid-keyword", foreground: "000000" }, // 黑色 (表示无效字段)
        { token: "custom-function", foreground: "2153d4" }, // 蓝色
        { token: 'delimiter.parenthesis', foreground: '2153d4' }
      ],
      colors: {
        // 你还可以在这里覆盖编辑器的其他颜色
      },
    });

    // 应用我们的主题
    monaco.editor.setTheme("myCoolTheme");

    // --- 4. (可选) 添加自动补全功能 ---
    completionProviderRef.current = monaco.languages.registerCompletionItemProvider(languageId, {
      provideCompletionItems: (model, position) => {
        // 创建建议列表
        const suggestions1 = myKeywords.map((keyword) => ({
          label: `[${keyword}]`, // 显示的标签
          kind: monaco.languages.CompletionItemKind.Field, // 类型为“字段”
          insertText: `[${keyword}]`, // 插入的文本
          documentation: `这是一个自定义字段: ${keyword}`, // 提示文档
          range: undefined, // 插入范围，undefined 表示由编辑器自动决定
        }));

        // 2. 获取当前正在输入的词
        const wordInfo = model.getWordUntilPosition(position);

        // 这个 range 很重要，它告诉 Monaco Editor 应该替换文本的范围
        // 比如，用户输入了 "s"，我们提供 "SUM"，编辑器就需要用 "SUM" 替换掉 "s"
        const range = {
          startLineNumber: position.lineNumber,
          endLineNumber: position.lineNumber,
          startColumn: wordInfo.startColumn,
          endColumn: wordInfo.endColumn,
        };

        // 3. 过滤我们的函数列表
        const filteredFunctions = CUSTOM_FUNCTIONS.filter(func =>
          func.label.toLowerCase().startsWith(wordInfo.word.toLowerCase())
        );

        // 4. 构建提示项
        const suggestions2 = filteredFunctions.map(func => ({
          label: func.label,
          kind: monaco.languages.CompletionItemKind.Function,
          documentation: func.documentation,
          detail: func.detail,
          insertText: func.insertText,
          // 关键！指定插入规则为代码片段，这样 ${1:value} 才能生效
          insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          range: range,
        }));

        return { suggestions: [...suggestions1, ...suggestions2] };
      },
    });
  }

  const [code, setCode] = useState("[产品名称] + SUM(100)");

  /**
  * 编辑器内容变化时的回调函数
  * @param {string} value - 编辑器中的最新内容
  */
  function handleEditorChange(value) {
    console.log(value);
    setCode(value);
  }

  return (
    <div>
      <h1>自定义字段高亮编辑器</h1>
      <p>尝试输入 `[产品`，会看到自动补全提示。只有 `[产品名称]` 等有效字段会变蓝。</p>
      <div style={{ width: 600, height: 300 }}>
        <Editor
          height="60vh"
          language={languageId} // 关键：使用我们注册的语言ID
          // defaultValue={"[产品名称] + [不存在的字段]"}
          value={code}
          // theme="vs" // 设置为浅色主题
          options={{
            lineNumbers: 'off', // 关闭行号
            minimap: {
              enabled: false, // 关闭 minimap
            },
          }}
          onChange={handleEditorChange}
          onMount={handleEditorDidMount}
        />
      </div>
    </div>
  );
}

export default CustomFormulaEditor;
